package com.intermancer.predictor.system;

import java.util.List;

import com.intermancer.predictor.breed.BreedStrategy;
import com.intermancer.predictor.feeder.Feeder;
import com.intermancer.predictor.organism.Organism;
import com.intermancer.predictor.organism.OrganismRegistry;
import com.intermancer.predictor.select.SelectStrategy;
import com.intermancer.predictor.store.StoreEntry;
import com.intermancer.predictor.store.StoreEntryDAO;

public class Demiurge {
	
	public static void fillStoreEntryDAO(StoreEntryDAO storeEntryDAO, 
			OrganismRegistry organismRegistry, int maxSize, Feeder feeder,
			BreedStrategy breedStrategy, SelectStrategy selectStrategy) {
		drawFromRegistry(storeEntryDAO, organismRegistry, maxSize, feeder);
		fillWithOffspring(storeEntryDAO, maxSize, feeder, breedStrategy,
				selectStrategy);
	}

	private static void drawFromRegistry(StoreEntryDAO storeEntryDAO,
			OrganismRegistry organismRegistry, int maxSize, Feeder feeder) {
		for(Organism organism : organismRegistry.getOrganisms()) {
			StoreEntry storeEntry 	= evaluateAndStore(organism, feeder,
					storeEntryDAO, maxSize);
			if(storeEntry == null) {
				break;
			}
		}
	}
	
	private static StoreEntry evaluateAndStore(Organism organism, Feeder feeder,
			StoreEntryDAO storeEntryDAO, int maxSize) {
		StoreEntry storeEntry = null;
		if(storeEntryDAO.getSize() < maxSize) {
			storeEntry = new StoreEntry();
			storeEntry.setOrganism(organism);
			feeder.setOrganism(organism);
			feeder.init();
			feeder.feedOrganism();
			storeEntry.setScore(feeder.getEvaluator().getScore());
			storeEntryDAO.put(storeEntry);
		}
		return storeEntry;
	}

	private static void fillWithOffspring(StoreEntryDAO storeEntryDAO,
			int maxSize, Feeder feeder, BreedStrategy breedStrategy,
			SelectStrategy selectStrategy) {
		outer: while(storeEntryDAO.getSize() < maxSize) {
			List<Organism> parents = selectStrategy.choose(storeEntryDAO);
			List<Organism> children = breedStrategy.breed(parents);
			for(Organism child : children) {
				StoreEntry storeEntry = evaluateAndStore(child, feeder, storeEntryDAO, maxSize);
				if(storeEntry == null) {
					break outer;
				}
			}
		}
	}


}
